// David Andersen

using UnityEngine;
using System.Collections;

public class BSPGUI : MonoBehaviour {
	
	public Texture2D black;
	public Texture2D white;
	public Texture2D baseTileMap;
	
	private float dungeonSize = 32;
	private float splitRatio = 0.7F;
	private float splitRange = 0.3F;
	private int nodeTotal = 1;
	private int roomTotal = 1;
	private BSPNode rootNode;
	private Rect[] splits;
	private Rect[] rooms;
	private Rect[] corridors;
	private bool splitDraw = false;
	private bool roomDraw = false;
	private bool corridorDraw = false;
	private int[,] tileMap;
	private Texture2D[] tiles;
	
	void Start ()
	{
		GenerateDungeon();
	}
	
	void OnGUI ()
	{
		GUILayout.BeginArea(new Rect(10,10,128,512));
		GUILayout.BeginVertical();
		
		GUILayout.Label("Dungeon Size: " + dungeonSize.ToString());
		dungeonSize = GUILayout.HorizontalSlider(dungeonSize,32,512);
		if(Mathf.IsPowerOfTwo(Mathf.RoundToInt(dungeonSize)) == false)
		{
			dungeonSize = Mathf.ClosestPowerOfTwo(Mathf.RoundToInt(dungeonSize));
		}
		
		GUILayout.Label("Split Ratio: " + splitRatio.ToString());
		splitRatio = (Mathf.RoundToInt(GUILayout.HorizontalSlider(splitRatio,0.1F,0.9F) * 10)) * 0.1F;
		
		GUILayout.Label("Split Range: " + splitRange.ToString());
		splitRange = (Mathf.RoundToInt(GUILayout.HorizontalSlider(splitRange,0.0F,0.9F) * 10)) * 0.1F;
		
		if(GUILayout.Button("Split"))
		{			
			rootNode.Split(splitRatio,splitRange);
			nodeTotal = rootNode.CountNodes(nodeTotal);
			roomTotal = rootNode.CountRooms(nodeTotal);
			splits = new Rect[nodeTotal];
			rootNode.TraverseSplit(splits);
			splitDraw = true;
			roomDraw = false;
			corridorDraw = false;
		}
		
		if(GUILayout.Button("Generate Rooms"))
		{
			rootNode.GenerateRoom();
			rooms = new Rect[roomTotal];
			rootNode.TraverseRooms(rooms,roomTotal);
			roomDraw = true;
			splitDraw = false;
			corridorDraw = false;
		}
		
		if(GUILayout.Button("Generate Corridors"))
		{
			rootNode.GenerateCorridors(rooms,roomTotal);
			corridors = new Rect[nodeTotal - roomTotal];
			rootNode.TraverseCorridors(corridors);
			corridorDraw = true;
			splitDraw = false;
		}
		
		if(GUILayout.Button("Generate Rooms\n and Corridors"))
		{
			rootNode.GenerateRoom();
			rooms = new Rect[roomTotal];
			rootNode.TraverseRooms(rooms,roomTotal);
			rootNode.GenerateCorridors(rooms,roomTotal);
			corridors = new Rect[nodeTotal - roomTotal];
			rootNode.TraverseCorridors(corridors);
			roomDraw = true;
			splitDraw = false;
			corridorDraw = true;
		}
		
		if(GUILayout.Button("Reset"))
		{
			GenerateDungeon();
		}
		
		GUILayout.Label(nodeTotal.ToString());
		GUILayout.Label(roomTotal.ToString());
		GUILayout.Label(dungeonSize.ToString());
		GUILayout.Label(splitRatio.ToString());
		
		if(GUI.changed)
		{
			Reset();
		}
		
		GUILayout.EndVertical();
		GUILayout.EndArea();
		
		GUILayout.BeginArea(new Rect(200,10,dungeonSize,dungeonSize));
		
		if(Event.current.type.Equals(EventType.Repaint))
			{				
				Graphics.DrawTexture(new Rect(0,0,dungeonSize,dungeonSize), white);
			}
		
		if(splitDraw == true)
		{
			if(Event.current.type.Equals(EventType.Repaint))
			{				
				for(int i = 0; i < nodeTotal; i++)
				{
					Graphics.DrawTexture(splits[i], black);
				}
			}
		}
		
		if(roomDraw == true)
		{
			if(Event.current.type.Equals(EventType.Repaint))
			{				
				for(int i = 0; i < roomTotal; i++)
				{
					Graphics.DrawTexture(rooms[i], black);
				}
			}
		}
		
		if(corridorDraw == true)
		{
			if(Event.current.type.Equals(EventType.Repaint))
			{				
				for(int i = 0; i < (nodeTotal - roomTotal); i++)
				{
					Graphics.DrawTexture(corridors[i], black);
				}
			}
		}
				
		GUILayout.EndArea();
		
		GUILayout.BeginArea(new Rect(720,10,dungeonSize,dungeonSize));
		
		if(Event.current.type.Equals(EventType.Repaint))
			{				
				for(int i = 0; i < (nodeTotal - roomTotal); i++)
				{
					DrawTileMap();
				}
			}
		
		GUILayout.EndArea();
				
	}
	
	void Reset()
	{
		rootNode = new BSPNode(0,0,dungeonSize,dungeonSize,1);
		splitDraw = false;
		roomDraw = false;
		corridorDraw = false;
		nodeTotal = 1;
		roomTotal = 1;
	}
	
	void GenerateDungeon()
	{
		nodeTotal = 1;
		roomTotal = 1;
		splitDraw = false;
		roomDraw = false;
		corridorDraw = false;		
		rootNode = new BSPNode(0,0,dungeonSize,dungeonSize,1);
		
		for(int i = 0; i < 4; i++)
		{
			rootNode.Split(splitRatio,splitRange);			
		}
		nodeTotal = rootNode.CountNodes(nodeTotal);
		roomTotal = rootNode.CountRooms(nodeTotal);
		splits = new Rect[nodeTotal];
		rootNode.TraverseSplit(splits);
		rootNode.GenerateRoom();
		rooms = new Rect[roomTotal];
		rootNode.TraverseRooms(rooms,roomTotal);
		rootNode.GenerateCorridors(rooms,roomTotal);
		corridors = new Rect[nodeTotal - roomTotal];
		rootNode.TraverseCorridors(corridors);
		splitDraw = false;
		roomDraw = true;
		corridorDraw = true;
		CreateTiles();
		CreateTileMap();
		DrawTileMap();
	}
	
	void CreateTiles()
	{
		tiles = new Texture2D[9];
		int i = 0;
		for(int row = 0; row < 3; row++)
		{
			for(int col = 0; col < 3; col++)
			{
				tiles[i] = new Texture2D(16,16,TextureFormat.ARGB32,false);
				tiles[i].SetPixels(baseTileMap.GetPixels(row * 16,col * 16,16,16));
				tiles[i].Apply();
				i++;
			}
		}
	}
	
	void CreateTileMap()
	{
		tileMap = new int[(int)dungeonSize,(int)dungeonSize];
		for(int row = 0; row < dungeonSize; row++)
		{
			for(int col = 0; col < dungeonSize; col++)
			{
				for(int i = 0; i < roomTotal; i++)
				{
					if(rooms[i].x < col && rooms[i].x + rooms[i].width > col && rooms[i].y < row && rooms[i].y + rooms[i].height > row)
					{
						tileMap[col,row] = 3;
					}
					else
					{
						tileMap[col,row] = 4;
					}
				}
				for(int i = 0; i < (nodeTotal - roomTotal); i++)
				{
					if(corridors[i].x < col && corridors[i].x + corridors[i].width > col && corridors[i].y < row && corridors[i].y + corridors[i].height > row)
					{
						tileMap[col,row] = 3;
					}
					else
					{
						tileMap[col,row] = 4;
					}
				}
			}
		}
	}
	
	void DrawTileMap()
	{
		for(int row = 0; row < 15; row++)
		{
			for(int col = 0; col < 15; col++)
			{
				Graphics.DrawTexture(new Rect(col * 16,row * 16,16,16),tiles[tileMap[col,row]]);
			}
		}
	}
}
